package org.soar.net;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;

import com.google.common.base.Charsets;
import com.google.inject.Singleton;

@Singleton
public class NetConnection {
	
	private Charset charset = Charsets.UTF_8;
	private String encode = charset.name();
	
	public JSONObject get(String urlString,Map paramsMap,PreRequestListener preRequestListener,PostResponseListener postResponseListener) {
		String params = this.processGetParams(paramsMap);
		// HttpGet连接对象
		HttpGet httpRequest = new HttpGet(urlString+params);
		HttpResponse httpResponse = (HttpResponse) this.connect(httpRequest,preRequestListener,postResponseListener);
		return processReturnJSONObject(httpResponse);
	}
	
	public InputStream getForInputStream(String urlString,Map paramsMap,PreRequestListener preRequestListener,PostResponseListener postResponseListener) {
		String params = this.processGetParams(paramsMap);
		HttpGet httpRequest = new HttpGet(urlString+params);
		try {
			HttpResponse httpResponse = (HttpResponse) this.connect(httpRequest,preRequestListener,postResponseListener);
			if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				// 取得返回的输出流
				InputStream is = httpResponse.getEntity().getContent();
				return is;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public JSONObject post(String urlString, Map<String,Object> paramsMap,PreRequestListener preRequestListener,PostResponseListener postResponseListener) {
		// HttpPost连接对象
		HttpPost httpRequest = new HttpPost(urlString);
		// 使用NameValuePair来保存要传递的Post参数
		List<NameValuePair> params = this.processPostParams(paramsMap);
		// 设置字符集
		HttpEntity httpentity = null;
		try {
			httpentity = new UrlEncodedFormEntity(params, encode);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		// 请求httpRequest
		httpRequest.setEntity(httpentity);
		HttpResponse httpResponse = (HttpResponse) this.connect(httpRequest,preRequestListener,postResponseListener);
		return processReturnJSONObject(httpResponse);
	}
	
	public JSONObject postForFile(String urlString, Map<String,Object> paramsMap,PreRequestListener preRequestListener,PostResponseListener postResponseListener) {
		// HttpPost连接对象
		HttpPost httpRequest = new HttpPost(urlString);
		MultipartEntity mpEntity = new MultipartEntity();  
        if (paramsMap != null && !paramsMap.isEmpty()) {
        	try {
	            for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {  
	            	String key = entry.getKey();
	            	if(entry.getValue() instanceof File){
	            		FileBody fb = new FileBody((File) entry.getValue());
	            		mpEntity.addPart(key,fb);
	            	}else if(entry.getValue() instanceof File[]){
	            		File[] files = (File[]) entry.getValue();
	            		for(File file : files){
	            			FileBody fb = new FileBody(file);
		            		mpEntity.addPart(key,fb);
	            		}
	            	}else{
	            		String value = String.valueOf(entry.getValue());
	            		StringBody par = new StringBody(value,charset);
	            		mpEntity.addPart(key, par);  
	            	}
	            }
        	} catch (UnsupportedEncodingException e) {
        		e.printStackTrace();
        	}  
        }
        
		// 请求httpRequest
		httpRequest.setEntity(mpEntity);
		HttpResponse httpResponse = (HttpResponse) this.connect(httpRequest,preRequestListener,postResponseListener);
		return processReturnJSONObject(httpResponse);
	}
	
	
	private Object connect(HttpRequestBase httpRequest,PreRequestListener preRequestListener,PostResponseListener postResponseListener){
		HttpClient httpclient = new DefaultHttpClient();
		// 取得HttpResponse
		try {
			preRequest(httpRequest,preRequestListener);
			HttpResponse httpResponse = httpclient.execute(httpRequest);
			postResponse(httpResponse,postResponseListener);
			// HttpStatus.SC_OK表示连接成功
			return httpResponse;
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	private void preRequest(HttpRequestBase request,PreRequestListener preRequestListener){
		if(request instanceof HttpGet){
			request.setHeader("Content-Type","application/x-www-form-urlencoded; charset="+encode);
		}else if(request instanceof HttpPost){
			request.addHeader("charset", encode);
		}
		if(preRequestListener != null){
			preRequestListener.preRequestSend(request);
		}
	}
	
	private void postResponse(HttpResponse response,PostResponseListener postResponseListener) {
		
		if(postResponseListener != null){
			postResponseListener.postResponseSend(response);
		}
	}
	
	private List<NameValuePair> processPostParams(Map<String,Object> paramsMap){
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		if(paramsMap != null){
			for(Iterator i = paramsMap.keySet().iterator(); i.hasNext(); ){
				String key = (String) i.next();
				String value = String.valueOf( paramsMap.get(key));
				params.add(new BasicNameValuePair(key, value));
			}
		}
		return params;
	}
	
	private String processGetParams(Map<String,Object> paramsMap){
		String params = "";
		if(paramsMap != null){
			try{
				int c = 0;
				for (Iterator i = paramsMap.keySet().iterator(); i.hasNext();) {
					String key = (String) i.next();
					String value = String.valueOf(paramsMap.get(key));
					if(c == 0){
						params += "?";
					}else{
						params += "&";
					}
					params = params + URLEncoder.encode(key, encode);
					params = params + "=";
					if(value != null){
						params = params + URLEncoder.encode(value, encode);
					}
					c++;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		//params = URLEncoder.encode(params);
		return params;
	}
	
	private JSONObject processReturnJSONObject(HttpResponse httpResponse){
		String strResult = null;
		// 请求成功
		if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
			// 取得返回的字符串
			try {
				strResult = EntityUtils.toString(httpResponse.getEntity(), encode);
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else {
			throw new ServerException(httpResponse.getStatusLine().getReasonPhrase());
		}
		JSONObject obj = null;
		try {
			obj = new JSONObject(strResult);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return obj;
	}
}
